package com.imooc.business.core.executor.collect;

import com.imooc.business.context.DataContext;
import com.imooc.business.domain.Collect;
import com.imooc.business.domain.Rule;
import com.imooc.business.util.DateUtil;
import com.imooc.infra.repository.jdbc.DynamicJdbcRepository;
import com.imooc.infra.repository.jdbc.params.StandardSqlParam;
import com.imooc.module.collect.enums.DimensionEnum;
import com.imooc.module.collect.enums.PeriodEnum;
import com.imooc.module.collect.request.ParamsRequest;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author Tim
 * @Description: 基础采集器
 * @Version 1.0
 */
@Component
public class BaseCollectProcess extends AbstractCollectProcess{

    private final DynamicJdbcRepository dynamicJdbcRepository;
    public BaseCollectProcess(DynamicJdbcRepository dynamicJdbcRepository) {
        this.dynamicJdbcRepository = dynamicJdbcRepository;
    }

    @Override
    public void collect(DataContext context) {
        Rule rule = context.getCacheModel().getRule();
        if (!checkCollect(rule)){
            return;
        }
        //构建sql查询参数
        Map<String, Object> params =  context.buildCollectParams();
        //初始化一下结果参数
        List<Map<String, Object>> results = context.buildCollectResult();
        List<Collect> collects = rule.getCollects();
        ParamsRequest request = context.getRequest();
        Date startTime = request.getStartTime();
        Date endTime = request.getEndTime();
        collects.parallelStream().forEach(collect -> {
            fomatTimeParams(params, startTime, endTime, collect.getPeriodFormat());
            String content = collect.getContent();
            switch (collect.getCollectWay()) {
                case SQL -> {
                   List<Map<String, Object>> queryResult = dynamicJdbcRepository.queryMapList(content, collect.getDataSource(), params);
                   combineResult(collect, results, queryResult);
                }
                case INTERFACE -> {
                    //接口方式的采集：交给小伙伴来实现
                }
            }
        });
        context.getCacheModel().getResults().addAll(filter(results, collects));
    }

    /**
     * 把当前查询到的结果(queryResult) 合并到初始结果里面(results)
     * @param collect
     * @param results
     * @param queryResult
     */
    private void combineResult(Collect collect, List<Map<String, Object>> results,
                               List<Map<String, Object>> queryResult) {
        if (CollectionUtils.isEmpty(queryResult)) {
            return;
        }
        //key: userId, value: map
        Map<Object, Map<String, Object>> userId2Map = queryResult.stream().collect(Collectors.toMap(map -> map.get(StandardSqlParam.USER_ID), v -> v));
        results.stream().forEach(map -> {
            Object userId = map.get(StandardSqlParam.USER_ID);
            Optional.ofNullable(userId2Map.get(userId)).map(m -> m.get(collect.getEnName())).ifPresent(indexValue -> map.put(collect.getEnName(), indexValue));
        });
    }

    @Override
    public PeriodEnum supportPeriod() {
        return PeriodEnum.DAY;
    }

    @Override
    public DimensionEnum supportDimension() {
        return DimensionEnum.USER;
    }
}
